home *** CD-ROM | disk | FTP | other *** search
/ SunSoft Catalyst CDWARE 1996 May to August / Catalyst CDWARE 1996 May to August.iso / .products / .bin / httpd / src / http_get.c < prev    next >
C/C++ Source or Header  |  1995-05-18  |  7KB  |  247 lines

  1. /*
  2.  * http_get.c: Handles things associated with GET
  3.  *
  4.  * All code contained herein is covered by the Copyright as distributed
  5.  * in the README file in the main directory of the distribution of 
  6.  * NCSA HTTPD.
  7.  * 
  8.  * Based on NCSA HTTPd 1.3 by Rob McCool
  9.  * 
  10.  * 04-08-95  blong
  11.  *    Fixed security hole which allowed a trailing slash on CGI_MAGIC_TYPE
  12.  *    cgi anywhere scripts to send back the script contents.  Now the
  13.  *    trailing slash is added to the PATH_INFO, and the script is run.
  14.  *    Oh yeah, and don't forget about directories.
  15.  */
  16.  
  17. #include "httpd.h"
  18.  
  19.  
  20. int header_only;
  21. int num_includes;
  22. int allow;
  23. char allow_options;
  24.  
  25.  
  26. void send_file(char *file, FILE *fd, struct stat *fi, 
  27.                char *path_args, char *args) 
  28. {
  29.     FILE *f;
  30.  
  31.     set_content_type(file);
  32.  
  33.     if((allow_options & OPT_INCLUDES) && (!content_encoding[0])) {
  34. #ifdef XBITHACK
  35.         if((fi->st_mode & S_IXUSR) ||
  36.            (!strcmp(content_type,INCLUDES_MAGIC_TYPE))) {
  37. #else
  38.         if(!strcmp(content_type,INCLUDES_MAGIC_TYPE)) {
  39. #endif
  40.             bytes_sent = 0;
  41.             send_parsed_file(file,fd,path_args,args,
  42.                              allow_options & OPT_INCNOEXEC);
  43.             log_transaction();
  44.             return;
  45.         }
  46.     }
  47.     if(!(f=fopen(file,"r"))) {
  48.         log_reason("file permissions deny server access",file);
  49.         unmunge_name(file);
  50.         die(FORBIDDEN,file,fd); /* we've already established that it exists */
  51.     }
  52.     bytes_sent = 0;
  53.     if(!assbackwards) {
  54.         set_content_length(fi->st_size);
  55.         if (set_last_modified(fi->st_mtime,fd)) {
  56.       fclose(f);
  57.       return;
  58.     }
  59.         send_http_header(fd);
  60.     }
  61.     num_includes=0;
  62.     if(!header_only) 
  63.         send_fd(f,fd,NULL);
  64.     log_transaction();
  65.     fclose(f);
  66. }
  67.  
  68. /* Almost exactly equalivalent to exec_cgi_script, but this one
  69.    gets all of the path info passed to it, instead of calling get_path_info */
  70.  
  71. void send_cgi(char *method, char *file, char *path_args, char *args, 
  72.               struct stat *finfo, int in, FILE *fd) 
  73. {
  74.     int m = M_GET;
  75.     int stub_returns;
  76.  
  77.     if((!strcmp(method,"GET")) || (!strcmp(method,"HEAD")))
  78.         m = M_GET;
  79.     else if(!strcmp(method,"POST"))
  80.         m = M_POST;
  81.     else if(!strcmp(method,"PUT"))
  82.         m = M_PUT;
  83.     else if(!strcmp(method,"DELETE"))
  84.         m = M_DELETE;
  85.  
  86.     evaluate_access(file,finfo,m,&allow,&allow_options,fd);
  87.     if((!allow) || (!(allow_options & OPT_EXECCGI))) {
  88.         log_reason("client denied by server configuration",file);
  89.         unmunge_name(file);
  90.         die(FORBIDDEN,file,fd);
  91.     }
  92.     if(!(in_headers_env = add_common_vars(in_headers_env,fd)))
  93.         die(NO_MEMORY,"send_cgi",fd);
  94.  
  95.     bytes_sent = 0;
  96.     stub_returns = cgi_stub(method,file,path_args,args,in_headers_env,finfo,in,fd);
  97.     free_env(in_headers_env);
  98.     in_headers_env = NULL;
  99.  
  100.     switch (stub_returns) {
  101.         case REDIRECT_URL:
  102.                 die(REDIRECT,location,fd);
  103.                 break;
  104.         case REDIRECT_LOCAL:
  105.                 break;
  106.         default:
  107.                 log_transaction();
  108.                 break;
  109.     }
  110. }
  111.  
  112.  
  113. void send_node(char *file, char *args, int in, FILE *fd)
  114. {
  115.     struct stat finfo;
  116.     char pa[MAX_STRING_LEN];
  117.     int length = 0;
  118.     register x = 0;
  119.  
  120. /* Remove all of the trailing slashes from the filename in order
  121.    to fix security hole.  All trailing slashes are placed in the 
  122.    path alias (pa) array */
  123.  
  124.     length = strlen(file);
  125.     while (length && (file[length-1] == '/') && (x < MAX_STRING_LEN)) {
  126.     pa[x] = '/';
  127.     x++;
  128.     file[length-1] = '\0';
  129.     length--;
  130.     }
  131.     pa[x] = '\0';
  132.     if(stat(file,&finfo) == -1) {
  133.         /* Look for script or include document */
  134.         int n=count_dirs(file),i,l;
  135.         char t[MAX_STRING_LEN];
  136.         
  137.         for(i=n;i;--i) {
  138.             make_dirstr(file,i,t);
  139.             probe_content_type(t);
  140.             if(!strcmp(content_type,CGI_MAGIC_TYPE)) {
  141.                 if(stat(t,&finfo) == -1)
  142.                     continue;
  143.                 if(!(S_ISREG(finfo.st_mode)))
  144.                     break;
  145.                 l=strlen(t);
  146.                 strncat(pa,&file[l],MAX_STRING_LEN - strlen(pa));
  147.                 file[l] = '\0';
  148.                 send_cgi("GET",file,pa,args,&finfo,in,fd);
  149.                 return;
  150.             } else if(!strcmp(content_type,INCLUDES_MAGIC_TYPE)) {
  151.                 if(stat(t,&finfo) == -1)
  152.                     continue;
  153.                 l=strlen(t);
  154.                 strncat(pa,&file[l],MAX_STRING_LEN - strlen(pa));
  155.                 file[l] = '\0';
  156.                 goto send_regular;
  157.             }
  158.         }
  159.         if(errno==ENOENT) {
  160.             log_reason("file does not exist",file);
  161.             unmunge_name(file);
  162.             die(NOT_FOUND,file,fd);
  163.         }
  164.         else {
  165.             log_reason("file permissions deny server access",file);
  166.             unmunge_name(file);
  167.             die(FORBIDDEN,file,fd);
  168.         }
  169.     }
  170.     probe_content_type(file);
  171.     if(S_ISREG(finfo.st_mode) && (!strcmp(content_type,CGI_MAGIC_TYPE))) {
  172.         send_cgi("GET",file,pa,args,&finfo,in,fd);
  173.         return;
  174.     }
  175.  
  176.   send_regular: /* aaaaack */
  177.     evaluate_access(file,&finfo,M_GET,&allow,&allow_options, fd);
  178.     if(!allow) {
  179.         log_reason("client denied by server configuration",file);
  180.         unmunge_name(file);
  181.         die(FORBIDDEN,file,fd);
  182.     }
  183.  
  184.     if(S_ISDIR(finfo.st_mode)) {
  185.         char ifile[HUGE_STRING_LEN];
  186.  
  187. /* Path Alias (pa) array should now have the trailing slash */
  188. /*        if(file[strlen(file) - 1] != '/') {  */
  189.         if (pa[0] != '/') {
  190.             char url[HUGE_STRING_LEN];
  191.             strcpy_dir(ifile,file);
  192.             unmunge_name(ifile);
  193.             construct_url(url,ifile);
  194.             escape_url(url);
  195.             die(REDIRECT,url,fd);
  196.         }
  197.         make_full_path(file,index_name,ifile);
  198.         if(stat(ifile,&finfo) == -1) {
  199.             if(allow_options & OPT_INDEXES)
  200.                 index_directory(file,fd);
  201.             else {
  202.                 log_reason("file permissions deny server access",file);
  203.                 unmunge_name(file);
  204.                 die(FORBIDDEN,file,fd);
  205.             }
  206.         }
  207.         else {
  208.             probe_content_type(ifile);
  209.             if(!strcmp(content_type,CGI_MAGIC_TYPE))
  210.                 send_cgi("GET",ifile,pa,args,&finfo,in,fd);
  211.             else
  212.                 send_file(ifile,fd,&finfo,pa,args);
  213.         }
  214.         return;
  215.     }
  216.     if(S_ISREG(finfo.st_mode)) 
  217.       send_file(file,fd,&finfo,pa,args);
  218.     else {
  219.         log_reason("improper file type",file);
  220.         unmunge_name(file);
  221.         die(FORBIDDEN,file,fd); /* device driver or pipe, no permission */
  222.     }
  223. }
  224.  
  225. void process_get(int in, FILE *out, char *m, char *url, char *args) {
  226.     int s;
  227.  
  228.     if(assbackwards && header_only) {
  229.         header_only = 0;
  230.         die(BAD_REQUEST,"Invalid HTTP/0.9 method.",out);
  231.     }
  232.     s=translate_name(url,out);
  233.     switch(s) {
  234.       case STD_DOCUMENT:
  235.         send_node(url,args,in,out);
  236.         return;
  237.       case REDIRECT_URL:
  238.         die(REDIRECT,url,out);
  239.       case SCRIPT_NCSA:
  240.         exec_get_NCSA(url,args,in,out);
  241.         return;
  242.       case SCRIPT_CGI:
  243.         exec_cgi_script(m,url,args,in,out);
  244.         return;
  245.     }
  246. }
  247.